package thread;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static print.Print.*;
class SleepBlock implements Runnable{
    @Override
    public void run() {
        try{
            TimeUnit.SECONDS.sleep(30);
        }catch (InterruptedException ex){
            print("InterruptedException");
        }
        print("Exit SleepBlocked.run");
    }
}

class IOBlock implements Runnable{
    private InputStream in;
    public IOBlock(InputStream in){
        this.in = in;
    }
    @Override
    public void run() {
        try{
            print("Waiting for read");
            in.read();
        }catch (IOException ex){
            if (Thread.currentThread().isInterrupted()){
                print("Interrupted from block I/O");
            }else{
                throw new RuntimeException(ex);
            }
        }
        print("Exiting IOBlocked.run");
    }
}

class SynchronizedBlocked implements Runnable{

    public synchronized void f(){
        while (true){
            Thread.yield();
        }
    }

    public SynchronizedBlocked(){
        new Thread(){
            @Override
            public void run() {
                f();
            }
        }.start();
    }

    @Override
    public void run() {
        print("Trying to call f()");
        f();
        print("Exiting SynchronizedBlocked.run");
    }
}

public class Interrupting {
    private static ExecutorService exec = Executors.newCachedThreadPool();
    static void test(Runnable r) throws InterruptedException{
        Future<?> f = exec.submit(r);
        TimeUnit.MILLISECONDS.sleep(100);
        print("Interrupting "+r.getClass().getName());
        f.cancel(true);
        print("Interrupt sent to "+r.getClass().getName());
    }

    public static void main(String[] args) throws Exception {
        test(new SleepBlock());
        test(new IOBlock(System.in));
        test(new SynchronizedBlocked());
        TimeUnit.MILLISECONDS.sleep(3000);
        print("Aborting with Systen exit(0)");
        System.exit(0);
    }
}
